using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using ycx;

namespace RFS.BizLogic.utils.impl
{
    public enum LogLevel
    {
        Debug,
        Info,
        Error
    }

    internal class Log : ILog
    {
        private string GetExceptionDetails(Exception ex, int level = 2)
        {
            if (ex == null)
                return "";

            StringBuilder sb = new StringBuilder();

            // 添加缩进
            sb.Append(new string(' ', level * 2));

            // 添加异常类型和消息
            sb.AppendLine($"Exception: {ex.GetType().FullName}");
            sb.Append(new string(' ', level * 2));
            sb.AppendLine($"Message: {ex.Message}");

            // 添加堆栈跟踪
            sb.Append(new string(' ', level * 2));
            sb.AppendLine("Stack Trace:");
            sb.Append(new string(' ', level * 2));
            sb.AppendLine(ex.StackTrace);

            // 递归处理内嵌异常
            if (ex.InnerException != null)
            {
                sb.AppendLine();
                sb.Append(new string(' ', level * 2));
                sb.AppendLine("Inner Exception:");
                GetExceptionDetailsInner(sb, ex.InnerException, level + 1);
            }

            return sb.ToString();

            string GetExceptionDetailsInner(StringBuilder sb2, Exception ex2, int level2)
            {
                if (ex2 == null)
                    return "";

                // 添加缩进
                sb2.Append(new string(' ', level2 * 2));

                // 添加异常类型和消息
                sb2.AppendLine($"Exception: {ex2.GetType().FullName}");
                sb2.Append(new string(' ', level2 * 2));
                sb2.AppendLine($"Message: {ex2.Message}");

                // 添加堆栈跟踪
                sb2.Append(new string(' ', level2 * 2));
                sb2.AppendLine("Stack Trace:");
                sb2.Append(new string(' ', level2 * 2));
                sb2.AppendLine(ex2.StackTrace);

                // 递归处理内嵌异常
                if (ex2.InnerException != null)
                {
                    sb2.AppendLine();
                    sb2.Append(new string(' ', level2 * 2));
                    sb2.AppendLine("Inner Exception:");
                    GetExceptionDetailsInner(sb2, ex2.InnerException, level2 + 1);
                }

                return sb2.ToString();
            }
        }


        public void Err(Exception ex)
        {
            OnAdded(Formate(ex.Message));
            onNewLogAdded(  Formate(ex.Message), LogLevel.Error );

            Log2File(GetExceptionDetails(ex));
        }

         


        public event EventHandler<string> NewLogAdded;
        public event EventHandler<(string log, LogLevel l)> NewLevedLogAdded;

        void onNewLogAdded(string log, LogLevel l)
        {
            NewLevedLogAdded?.Invoke(this, (log,l) );
        }

        string Formate(string msg)
        {
            return string.Format("[{0:mm:ss fff}] {1}", DateTime.Now, msg);
        }

        public void Info(string info)
        {
            NewLogAdded?.Invoke(this, Formate(info));
            onNewLogAdded(  Formate(info), LogLevel.Info );
            Log2File(info);
        }

        public void Debug(string ex)
        {
            OnAdded(Formate(ex));
            onNewLogAdded(  Formate(ex), LogLevel.Debug );

            Log2File(ex);
        }

        void OnAdded(string newa)
        {
            NewLogAdded?.Invoke(this, newa);
        }


        private const string LogFilePath = "log.txt";
        private const int MaxLogLines = 20;
        List<string> lines = new List<string>();

        void Log2File(string log)
        {
            lock (lines)
            {
                lines.Add(Formate(log) );
                if (lines.Count > MaxLogLines) lines.RemoveAt(0);
                1.DebounceExecute(() => File.WriteAllLines(LogFilePath, lines, Encoding.UTF8));
            }
        }
    }
}